﻿using AutoMapper;
using LView.CMS.Core.Helper;
using LView.CMS.Core.Options;
using LView.CMS.IServices;
using LView.CMS.Models;
using LView.CMS.ViewModels;
using LView.CMS.ViewModels.Manager;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using SQLBuilder.Core.Repositories;
using SQLBuilder.Core;
using System.Text;
using LView.CMS.Core.Extensions;

namespace LView.CMS.Services
{
    public class ManagerService : ServiceBase, IManagerService
    {
        private readonly IMapper _mapper;
        private readonly IOptionsSnapshot<DbOption> _option;
        private readonly IRepository _repository;

        public ManagerService(IMapper mapper, IOptionsSnapshot<DbOption> options, Func<string, IRepository> handler)
        {
            _mapper = mapper;
            _option = options;
            _repository = handler(null);
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<LMSManager> SignInAsync(LoginModel model)
        {
            model.Password = AESEncryptHelper.Encode(model.Password.Trim(), LViewCMSKeys.AesEncryptKeys);
            model.UserName = model.UserName.Trim();
            var manager = await _repository.FindEntityAsync<LMSManager>(x => (x.UserName == model.UserName || x.Mobile == model.UserName || x.Email == model.UserName) && x.Password == model.Password);
            if (manager != null)
            {
                manager.LoginLastTime = DateTime.Now;
                manager.LoginCount += 1;
                manager.LoginLastIp = model.Ip;
                _repository.Update<LMSManager>(manager);

                var managerLog = new LMSManagerLog
                {
                    Id = Guid.NewGuid().ToString(),
                    ActionType = CzarCmsEnums.ActionEnum.SignIn.ToString(),
                    AddManagerId = manager.Id,
                    AddManagerNickName = manager.NickName,
                    AddTime = DateTime.Now,
                    AddIP = model.Ip,
                    Remark = "用户登录"
                };
                await _repository.InsertAsync<LMSManagerLog>(managerLog);
            }
            return manager;
        }

        public async Task<LMSManager> GetManagerByCondition(ManagerAddOrModifyModel model)
        {
            var sql = new StringBuilder("SELECT * FROM LMSMANAGER WHERE 1 = 1");
            if (!string.IsNullOrEmpty(model.UserName))
            {
                sql.Append($"AND USERNAME LIKE '%:USERNAME%'");
            }
            var manager = await _repository.FindEntityAsync<LMSManager>(sql.ToString(), new { USERNAME = model.UserName });
            if (manager != null)
                return manager;
            else
                return new LMSManager();
        }

        /// <summary>
        /// 添加/修改用户信息
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<BaseResult> AddOrModifyAsync(ManagerAddOrModifyModel model)
        {
            var result = new BaseResult();
            LMSManager manager;
            if (string.IsNullOrEmpty(model.Id))
            {
                //manager = _mapper.Map<LMSManager>(model);
                manager = model.MapTo<LMSManager>();
                manager.Password = AESEncryptHelper.Encode(LViewCMSKeys.DefaultPassword, LViewCMSKeys.AesEncryptKeys);
                manager.LoginCount = 0;
                manager.Id = Guid.NewGuid().ToString();
                manager.AddManagerId = Guid.NewGuid().ToString();
                manager.AddTime = DateTime.Now;
                manager.IsLock = 0;
                manager.Avatar = "/images/DefaultAvatar.png";  //添加用户默认头像
                manager.IsDelete = 0;
                if (await _repository.InsertAsync<LMSManager>(manager) > 0)
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonObjectSuccessCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonObjectSuccessMsg;
                }
                else
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonExceptionCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonExceptionMsg;
                }
            }
            else
            {
                manager = await _repository.FindEntityAsync<LMSManager>(x => x.Id == model.Id);
                if (manager != null)
                {
                    manager = model.MapTo<LMSManager>();
                    manager.ModifyManagerId = Claims.UserID;
                    manager.ModifyTime = DateTime.Now;
                    if (await _repository.UpdateAsync<LMSManager>(manager) > 0)
                    {
                        result.ResultCode = ResultCodeAddMsgKeys.CommonObjectSuccessCode;
                        result.ResultMsg = ResultCodeAddMsgKeys.CommonObjectSuccessMsg;
                    }
                    else
                    {
                        result.ResultCode = ResultCodeAddMsgKeys.CommonExceptionCode;
                        result.ResultMsg = ResultCodeAddMsgKeys.CommonExceptionMsg;
                    }
                }
                else
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonFailNoDataCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonFailNoDataMsg;
                }
            }
            return result;
        }

        /// <summary>
        /// 删除用户--物理删除
        /// </summary>
        /// <param name="Ids"></param>
        /// <returns></returns>
        public async Task<BaseResult> DeleteIdsAsync(string[] Ids)
        {
            var result = new BaseResult();
            var count = 0;
            if (Ids.Count() == 0)
            {
                result.ResultCode = ResultCodeAddMsgKeys.CommonModelStateInvalidCode;
                result.ResultMsg = ResultCodeAddMsgKeys.CommonModelStateInvalidMsg;
            }
            else
            {
                try
                {
                    await Task.Run(() =>
                    {
                        Ids.ToList().ForEach(async x =>
                        {
                            await _repository.DeleteAsync<LMSManager>(p => p.Id == x);
                            count++;
                        });
                    });
                }
                catch (Exception ex)
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonExceptionCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonExceptionMsg + $":{ex.Message}";
                }

                if (count > 0)
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonObjectSuccessCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonObjectSuccessMsg;
                }
            }
            return result;
        }

        /// <summary>
        /// 加载用户数据
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<TableDataModel> LoadDataAsync(ManagerRequestModel model)
        {
            var sql = new StringBuilder($@"
                WITH T AS(
                SELECT AA.*, BB.ROLENAME AS ROLENAME
                    FROM LMSMANAGER AA
                INNER JOIN LMSManagerRole BB
                    ON AA.ROLEID = BB.ID
                WHERE AA.ISDELETE = :ISDELETE");
            if (!string.IsNullOrEmpty(model.Key))
                sql.Append($" AND USERNAME LIKE '%{model.Key}%'");
            sql.Append(")");
            var (recordList, recordCount) = await _repository.FindListByWithAsync<LMSManager>(sql.ToString(), new { ISDELETE = 0 }, "AA.Id", true, model.Limit, model.Page);
            var viewList = new List<ManagerListModel>();
            recordList?.ToList().ForEach(x =>
            {
                //var item = _mapper.Map<ManagerListModel>(x);
                var item = x.MapTo<ManagerListModel>();
                viewList.Add(item);
            });
            return new TableDataModel
            {
                count = (int)recordCount,
                data = viewList,
            };
        }

        /// <summary>
        /// 变更用户锁定状态
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public async Task<BaseResult> ChangeLockStatusAsync(ChangeStatusModel model)
        {
            var result = new BaseResult();
            //var oridata = await _repository.FindEntityAsync<LMSManager>(model.Id);
            var oridata = await _repository.FindEntityAsync<LMSManager>(x => x.Id == model.Id);
            if (oridata.IsLock != model.Status)
            {
                oridata.IsLock = model.Status;
                var count = await _repository.UpdateAsync(oridata);
                if (count > 0)
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonObjectSuccessCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonObjectSuccessMsg;
                }
                else
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonExceptionCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonExceptionMsg;
                }
            }
            else
            {
                result.ResultCode = ResultCodeAddMsgKeys.CommonDataStatusChangeCode;
                result.ResultMsg = ResultCodeAddMsgKeys.CommonDataStatusChangeMsg;
            }
            return result;
        }

        /// <summary>
        /// 修改密码
        /// </summary>
        /// <param name="model">修改密码实体</param>
        /// <returns>结果</returns>
        public async Task<BaseResult> ChangePasswordAsync(ChangePasswordModel model)
        {
            BaseResult result = new BaseResult();
            var oriData = await _repository.FindEntityAsync<LMSManager>(x => x.Id == model.Id);
            if (oriData.Password == AESEncryptHelper.Encode(model.OldPassword, LViewCMSKeys.AesEncryptKeys))
            {
                var newPassword = AESEncryptHelper.Encode(model.NewPassword, LViewCMSKeys.AesEncryptKeys);
                oriData.Password = newPassword;
                var count = await _repository.UpdateAsync(oriData);
                if (count > 0)
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonObjectSuccessCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonObjectSuccessMsg;
                }
                else
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonExceptionCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonExceptionMsg;
                }
            }
            else
            {
                result.ResultCode = ResultCodeAddMsgKeys.OldPasswordErrorCode;
                result.ResultMsg = ResultCodeAddMsgKeys.OldPasswordErrorMsg;
            }
            return result;
        }

        /// <summary>
        /// 获取个人资料By ID
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<LMSManager> GetManagerByIdAsync(string id)
        {
            return await _repository.FindEntityAsync<LMSManager>(id);
        }

        /// <summary>
        /// 获取当前登陆人个人资料
        /// </summary>
        /// <returns></returns>
        public async Task<LMSManager> GetCurrManagerByIdAsync(string psd)
        {
            var Password = AESEncryptHelper.Encode(psd.Trim(), LViewCMSKeys.AesEncryptKeys);
            return await _repository.FindEntityAsync<LMSManager>(x => x.UserName == Claims.UserName && x.Password == Password);
        }

        /// <summary>
        /// 通过角色ID取个人资料
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<LMSManager>> GetManagerByRoleid(string id)
        {
            return (await _repository.FindListAsync<LMSManager>(x => x.RoleId == id)).ToList();
        }

        /// <summary>
        /// 取含角色名称的个人资料
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<LMSManager> GetManagerContainRoleNameByIdAsync(string id)
        {
            //
            var sql = @"
SELECT MR.ROLENAME,
       M.ID,
       M.ROLEID,
       M.USERNAME,
       M.PASSWORD,
       M.AVATAR,
       M.NICKNAME,
       M.MOBILE,
       M.EMAIL,
       M.LOGINCOUNT,
       M.LOGINLASTIP,
       M.LOGINLASTTIME,
       M.ADDMANAGERID,
       M.ADDTIME,
       M.MODIFYMANAGERID,
       M.MODIFYTIME,
       M.ISLOCK,
       M.ISDELETE,
       M.REMARK
  FROM LMSMANAGER M
 INNER JOIN LMSManagerRole MR
    ON M.ROLEID = MR.ID
 WHERE M.ID = :ID
   AND M.ISDELETE = 0
";
            return await _repository.FindEntityAsync<LMSManager>(sql, new
            {
                ID = id
            });
        }

        /// <summary>
        /// 个人资料修改
        /// </summary>
        /// <param name="model">个人资料修改实体</param>
        /// <returns>结果</returns>
        public async Task<BaseResult> UpdateManagerInfoAsync(ChangeInfoModel model)
        {
            BaseResult result = new BaseResult();
            //TODO Modify
            var manager = await _repository.FindEntityAsync<LMSManager>(x => x.Id == model.Id);
            if (manager != null)
            {
                manager = model.MapTo<LMSManager>();
                manager.ModifyManagerId = Claims.UserID;
                if (await _repository.UpdateAsync(manager) > 0)
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonObjectSuccessCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonObjectSuccessMsg;
                }
                else
                {
                    result.ResultCode = ResultCodeAddMsgKeys.CommonExceptionCode;
                    result.ResultMsg = ResultCodeAddMsgKeys.CommonExceptionMsg;
                }
            }
            else
            {
                result.ResultCode = ResultCodeAddMsgKeys.CommonFailNoDataCode;
                result.ResultMsg = ResultCodeAddMsgKeys.CommonFailNoDataMsg;
            }
            return result;
        }
    }
}
